package com.module.ble.widget

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.common.base.utils.ViewUtils
import com.common.base.utils.ViewUtils.dp2px
import com.common.base.utils.ViewUtils.sp2px
import com.module.ble.R
import com.module.ble.data.bean.CusChartData

/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：2025/07/15
 *
 * 描述：睡眠心率曲线图表控件
 * 支持自定义Y轴阶段配置、X轴时间标签、触摸交互和背景柱等功能
 * 修订历史：1. 连续有效数据点 ：正常绘制平滑曲线段
 *2.孤立点的线段斜度计算 ：
 *- 如果左右都有有效数据点：根据左右两点计算斜率
 *- 如果只有一边有有效数据点：延续该方向的斜率
 *- 如果左右都没有有效数据点：绘制水平线段
 *- 视觉效果更自然 ：孤立点的短线段会呈现出符合数据趋势的斜度，而不是生硬的水平线
 *3.断开效果 ：当遇到 mValue = 0.0 的数据点时，曲线自然断开
 *
 */
class SleepHrCurveNewChart @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    // 触摸监听器接口
    interface OnBarTouchListener {
        fun onBarTouched(index: Int, minValue: Float, maxValue: Float, timeLabel: String)
        fun onTouchReleased()
    }

    // 画笔
    private val barPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 柱状图画笔（保留用于背景柱）
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 文字画笔
    private val yAxisTextPaint = Paint(Paint.ANTI_ALIAS_FLAG) // Y轴标记文字画笔
    private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 背景画笔
    private val touchLinePaint = Paint(Paint.ANTI_ALIAS_FLAG) // 触摸实线画笔
    private val backgroundBarPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 背景柱画笔
    private val valueTextPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 数值文本画笔

    // 添加曲线绘制画笔
    private val curvePaint = Paint(Paint.ANTI_ALIAS_FLAG) // 曲线画笔
    private val curvePointPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 曲线点画笔

    // 矩形区域
    private val rectF = RectF()

    // 数据相关
    private var dataValues = mutableListOf<CusChartData>()
    private var timeLabels = arrayOf("00:00", "06", "12", "18", "24:00")

    // Y轴阶段配置（可从外部设置）
    private var yAxisStages = floatArrayOf(0f, 50f, 100f) // 默认三个阶段

    // 触摸相关
    private var touchListener: OnBarTouchListener? = null
    private var isTouching = false
    private var touchedBarIndex = -1
    private var touchLineX = 0f

    // 颜色配置
    private var activeBarColor = ViewUtils.getColor(R.color.c_5282ff) // 蓝色
    private var inactiveBarColor = ViewUtils.getColor(R.color.color_d9d9d9) // 灰色
    private var textColor = ViewUtils.getColor(R.color.c_7f7f7f)
    private var gridLineColor = ViewUtils.getColor(R.color.color_d9d9d9)
    private var chartBackgroundColor = ViewUtils.getColor(R.color.color_FAFAFA) // 柱状图背景色
    private var touchLineColor = ViewUtils.getColor(R.color.black) // 触摸实线颜色

    // 尺寸配置
    private var barSpacing = dp2px(2f)
    private var textSize = sp2px(12f)
    private var chartPaddingTop = dp2px(5f)
    private var chartPaddingBottom = dp2px(30f)

    // Y轴色块相关尺寸
    private var yAxisTextSize = sp2px(10f) // Y轴标记文字大小
    private var yAxisTextMargin = dp2px(5f) // 标记文字距离右边的间距

    private var yAxisTextEx:String?= "" // Y轴mark文字拼接内容

    // 柱子圆角控制变量
    private var enableBarTopRounding = true // 控制柱子顶部圆角
    private var enableBarBottomRounding = true // 控制柱子底部圆角

    // X轴中间线控制变量
    private var enableXAxisSolidLine = false // 控制X轴中间线绘制方式

    // 基准值相关属性
    private val basicLinePaint = Paint(Paint.ANTI_ALIAS_FLAG) // 基准线画笔
    private var mBasic: Float = 0f // 基准值
    private var basicBarColor = ViewUtils.getColor(R.color.c_5282ff) // 基准线颜色

    // Y轴区间背景相关属性
    private var yRangeBackgroundEnabled = false // 是否启用Y轴区间背景
    private var yRangeStartValue = 0f // 区间开始值
    private var yRangeEndValue = 0f // 区间结束值
    private var yRangeBackgroundColor = ViewUtils.getColor(R.color.c_5282ff) // 区间背景色
    private val yRangeBackgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG) // 区间背景画笔

    init {
        // 获取自定义属性
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.CandlestickChart)
        activeBarColor = typedArray.getColor(R.styleable.CandlestickChart_signs_candlestick_barDefaultColor, activeBarColor)
        yAxisTextEx = typedArray.getString(R.styleable.CandlestickChart_signs_candlestick_y_exText)
        typedArray.recycle()

        // 初始化画笔
        textPaint.color = textColor
        textPaint.textSize = textSize
        textPaint.textAlign = Paint.Align.CENTER

        // 初始化曲线画笔
        curvePaint.color = activeBarColor
        curvePaint.strokeWidth = dp2px(2f)
        curvePaint.style = Paint.Style.STROKE
        curvePaint.strokeCap = Paint.Cap.ROUND
        curvePaint.strokeJoin = Paint.Join.ROUND

        // 初始化曲线点画笔
        curvePointPaint.color = activeBarColor
        curvePointPaint.style = Paint.Style.FILL

        // 初始化数值文本画笔
        valueTextPaint.color = textColor
        valueTextPaint.textSize = sp2px(10f)
        valueTextPaint.textAlign = Paint.Align.CENTER
        valueTextPaint.typeface = Typeface.DEFAULT_BOLD

        // 初始化基准线画笔
        basicBarColor = activeBarColor
        basicLinePaint.color = basicBarColor
        basicLinePaint.strokeWidth = dp2px(1f)
        basicLinePaint.pathEffect = DashPathEffect(floatArrayOf(dp2px(2f), dp2px(2f)), 0f)
        basicLinePaint.style = Paint.Style.STROKE

        // 初始化Y轴标记文字画笔
        yAxisTextPaint.color = textColor
        yAxisTextPaint.textSize = yAxisTextSize
        yAxisTextPaint.textAlign = Paint.Align.LEFT

        // 初始化背景画笔
        backgroundPaint.color = chartBackgroundColor
        backgroundPaint.style = Paint.Style.FILL

        // 初始化触摸实线画笔
        touchLinePaint.color = touchLineColor
        touchLinePaint.strokeWidth = dp2px(1f)
        touchLinePaint.style = Paint.Style.STROKE

        // 初始化背景柱画笔
        backgroundBarPaint.color = ViewUtils.getColor(R.color.color_d9d9d9)
        backgroundBarPaint.style = Paint.Style.FILL

        // 初始化Y轴区间背景画笔
        yRangeBackgroundPaint.color = yRangeBackgroundColor
        yRangeBackgroundPaint.style = Paint.Style.FILL
        yRangeBackgroundPaint.alpha = 128 // 设置半透明效果
    }

    /**
     * 计算数据点的X坐标
     * 当只有一个数据点时，放在中心；多个数据点时，首尾贴紧边界，中间均匀分布
     */
    private fun calculatePointX(index: Int, availableWidth: Float): Float {
        return if (dataValues.size <= 1) {
            availableWidth / 2f
        } else {
            index * availableWidth / (dataValues.size - 1)
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)

        // 计算最小高度
        val minHeight = (chartPaddingTop + chartPaddingBottom + dp2px(200f)).toInt()
        val height = when (heightMode) {
            MeasureSpec.EXACTLY -> MeasureSpec.getSize(heightMeasureSpec)
            else -> minHeight
        }

        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        if (dataValues.isEmpty()) return

        val chartHeight = height - chartPaddingTop - chartPaddingBottom

        // 绘制柱状图背景
        drawChartBackground(canvas, chartHeight)

        // 绘制Y轴区间背景（在基准线之前绘制）
        if (yRangeBackgroundEnabled) {
            drawYRangeBackground(canvas, chartHeight)
        }

        // 绘制Y轴网格线
        drawYAxisGrid(canvas, chartHeight)

        // 绘制X轴网格线
        drawXAxisGrid(canvas, chartHeight)

        // 绘制基准线（在曲线之前绘制）
        drawBasicLine(canvas, chartHeight)

        // 绘制平滑曲线（替换原来的柱状图）
        drawCurve(canvas, chartHeight)

        // 绘制曲线上的指示点（替换原来的圆圈指示点）
        drawCurveIndicatorPoints(canvas, chartHeight)

        // 绘制触摸实线（在曲线之后绘制，确保在最上层）
        if (isTouching && touchedBarIndex >= 0) {
            drawTouchLine(canvas, chartHeight)
        }

        // 绘制X轴时间标签
        drawTimeLabels(canvas, chartHeight)

        // 绘制右侧Y轴标记文字
        drawYAxisStageIndicators(canvas, chartHeight)
    }

    /**
     * 绘制柱状图背景
     */
    private fun drawChartBackground(canvas: Canvas, chartHeight: Float) {
        // 计算Y轴文字区域的位置（去除色块宽度）
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 绘制背景矩形
        rectF.set(
            0f, // 左边界
            chartPaddingTop, // 上边界
            yAxisBarX, // 右边界（到Y轴文字左侧）
            chartPaddingTop + chartHeight // 下边界
        )
        canvas.drawRect(rectF, backgroundPaint)
    }

    /**
     * 绘制Y轴网格线
     */
    private fun drawYAxisGrid(canvas: Canvas, chartHeight: Float) {
        // 计算Y轴文字区域的位置（去除色块宽度）
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 柱状图起始位置（左对齐）
        val barsStartX = 0f

        // 网格线右边界：Y轴标记文字的右侧
        val gridLineEndX = yAxisBarX + yAxisTextMargin + maxTextWidth

        // 创建虚线画笔
        val dashedLinePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = gridLineColor
            strokeWidth = dp2px(1f)
            pathEffect = DashPathEffect(floatArrayOf(dp2px(2f), dp2px(2f)), 0f)
        }

        // 创建加粗实线画笔（用于顶部和底部）
        val boldLinePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
            color = gridLineColor
//            strokeWidth = dp2px(2f) // 加粗线条
            strokeWidth = dp2px(1f) // 加粗线条
        }

        // 获取Y轴范围
        val minValue = yAxisStages.first()
        val maxValue = yAxisStages.last()
        val valueRange = maxValue - minValue

        // 绘制Y轴网格线
        for (i in yAxisStages.indices) {
            val stage = yAxisStages[i]
            val normalizedStage = (stage - minValue) / valueRange

            when (i) {
                0 -> {
                    // 底部网格线（最小值）- 绘制在柱状图下方
                    val bottomY = chartPaddingTop + chartHeight + dp2px(1f) // 在图表底部下方1dp处
                    canvas.drawLine(
                        barsStartX,
                        bottomY,
                        gridLineEndX,
                        bottomY,
                        boldLinePaint
                    )
                }
                yAxisStages.size - 1 -> {
                    // 顶部网格线（最大值）- 加粗实线
                    val y = chartPaddingTop + chartHeight * (1 - normalizedStage) - dp2px(1f)
                    canvas.drawLine(
                        barsStartX,
                        y,
                        gridLineEndX,
                        y,
                        boldLinePaint
                    )
                }
                else -> {
                    // 中间的网格线 - 虚线
                    val y = chartPaddingTop + chartHeight * (1 - normalizedStage)
                    canvas.drawLine(
                        barsStartX,
                        y,
                        yAxisBarX,
                        y,
                        dashedLinePaint
                    )
                }
            }
        }
    }

    /**
     * 绘制X轴网格线
     */
    private fun drawXAxisGrid(canvas: Canvas, chartHeight: Float) {
        // 计算Y轴文字区域的位置（去除色块宽度）
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 根据开关选择绘制方式
        if (enableXAxisSolidLine) {
            // 绘制实线画笔
            val solidLinePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
                color = gridLineColor
                strokeWidth = dp2px(1f)
                style = Paint.Style.STROKE
            }

            // 绘制X轴网格线（包括首尾的时间标签位置）
            for (i in timeLabels.indices) {
                val gridLineX = when (i) {
                    0 -> 0f // 第一个标签（00:00）与图表左边对齐
                    timeLabels.size - 1 -> yAxisBarX // 最后一个标签位于图表右边界
                    else -> {
                        // 动态计算中间时间点的X位置
                        val segmentSize = yAxisBarX / (timeLabels.size - 1)
                        i * segmentSize
                    }
                }

                // 计算底部Y轴线的位置
                val bottomYAxisLine = chartPaddingTop + chartHeight + dp2px(1f)

                // 绘制从底部Y轴线开始向上8px高度的垂直实线
                canvas.drawLine(
                    gridLineX,
                    bottomYAxisLine, // 从底部Y轴线开始
                    gridLineX,
                    bottomYAxisLine - dp2px(8f), // 向上8px高度
                    solidLinePaint
                )
            }
        } else {
            // 创建虚线画笔用于X轴网格线
            val xAxisGridPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
                color = gridLineColor
                strokeWidth = dp2px(1f)
                pathEffect = DashPathEffect(floatArrayOf(dp2px(2f), dp2px(2f)), 0f)
            }

            // 绘制X轴网格线（除首尾的时间标签位置）
            for (i in 1 until timeLabels.size - 1) { // 跳过首尾（i=0和i=4）
                // 动态计算中间时间点的X位置
                val segmentSize = yAxisBarX / (timeLabels.size - 1)
                val gridLineX = i * segmentSize

                // 绘制从图表顶部到底部的垂直虚线
                canvas.drawLine(
                    gridLineX,
                    chartPaddingTop, // 图表顶部
                    gridLineX,
                    chartPaddingTop + chartHeight, // 图表底部
                    xAxisGridPaint
                )
            }
        }
    }

    /**
     * 绘制平滑曲线
     */
    private fun drawCurve(canvas: Canvas, chartHeight: Float) {
        if (dataValues.isEmpty()) return

        // 计算Y轴文字区域的位置
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 获取Y轴范围
        val yAxisMinValue = yAxisStages.first()
        val yAxisMaxValue = yAxisStages.last()
        val yAxisValueRange = yAxisMaxValue - yAxisMinValue

        // 先绘制背景柱
        drawBackgroundBars(canvas, chartHeight, yAxisBarX, yAxisMinValue, yAxisMaxValue, yAxisValueRange)

        // 将连续的有效数据点分组，同时记录孤立点的索引
        val validPointGroups = mutableListOf<MutableList<Pair<Int, Pair<Float, Float>>>>()
        val isolatedPointsWithIndex = mutableListOf<Pair<Int, Pair<Float, Float>>>() // 存储孤立点及其原始索引
        var currentGroup = mutableListOf<Pair<Int, Pair<Float, Float>>>()

        for (i in dataValues.indices) {
            val dataValue = dataValues[i].mValue

            if (dataValue > 0.0f) {
                // 有效数据点，添加到当前组
                val clampedValue = dataValue.coerceIn(yAxisMinValue, yAxisMaxValue)
                val normalizedValue = if (yAxisValueRange > 0) (clampedValue - yAxisMinValue) / yAxisValueRange else 0f
                val pointX = calculatePointX(i, yAxisBarX)
                val pointY = chartPaddingTop + chartHeight * (1 - normalizedValue)

                currentGroup.add(Pair(i, Pair(pointX, pointY)))
            } else {
                // 无效数据点（mValue = 0.0），结束当前组
                if (currentGroup.isNotEmpty()) {
                    if (currentGroup.size == 1) {
                        // 单个点，添加到孤立点列表
                        isolatedPointsWithIndex.add(currentGroup[0])
                    } else {
                        // 多个点，添加到正常组
                        validPointGroups.add(currentGroup)
                    }
                    currentGroup = mutableListOf()
                }
            }
        }

        // 添加最后一组（如果有的话）
        if (currentGroup.isNotEmpty()) {
            if (currentGroup.size == 1) {
                isolatedPointsWithIndex.add(currentGroup[0])
            } else {
                validPointGroups.add(currentGroup)
            }
        }

        // 定义图表边界
        val chartTop = chartPaddingTop
        val chartBottom = chartPaddingTop + chartHeight
        val chartLeft = 0f
        val chartRight = yAxisBarX

        // 为每组有效点绘制独立的曲线段
        for (pointGroup in validPointGroups) {
            if (pointGroup.size < 2) continue // 少于2个点无法绘制曲线

            // 创建平滑曲线路径
            val path = Path()
            val firstPoint = pointGroup[0].second
            path.moveTo(firstPoint.first, firstPoint.second)

            // 使用贝塞尔曲线创建平滑效果
            for (i in 1 until pointGroup.size) {
                val currentPoint = pointGroup[i].second
                val previousPoint = pointGroup[i - 1].second

                if (i == 1) {
                    // 第一段曲线，使用二次贝塞尔曲线
                    val controlX = (previousPoint.first + currentPoint.first) / 2
                    val controlY = (previousPoint.second + currentPoint.second) / 2

                    // 限制控制点在图表边界内
                    val clampedControlX = controlX.coerceIn(chartLeft, chartRight)
                    val clampedControlY = controlY.coerceIn(chartTop, chartBottom)

                    path.quadTo(clampedControlX, clampedControlY, currentPoint.first, currentPoint.second)
                } else {
                    // 后续曲线，使用三次贝塞尔曲线实现更平滑的效果
                    val prevPrevPoint = pointGroup[i - 2].second

                    // 计算控制点
                    val control1X = previousPoint.first + (currentPoint.first - prevPrevPoint.first) * 0.15f
                    val control1Y = previousPoint.second + (currentPoint.second - prevPrevPoint.second) * 0.15f

                    val control2X = currentPoint.first - (if (i < pointGroup.size - 1) {
                        (pointGroup[i + 1].second.first - previousPoint.first) * 0.15f
                    } else {
                        (currentPoint.first - previousPoint.first) * 0.15f
                    })
                    val control2Y = currentPoint.second - (if (i < pointGroup.size - 1) {
                        (pointGroup[i + 1].second.second - previousPoint.second) * 0.15f
                    } else {
                        (currentPoint.second - previousPoint.second) * 0.15f
                    })

                    // 限制控制点在图表边界内
                    val clampedControl1X = control1X.coerceIn(chartLeft, chartRight)
                    val clampedControl1Y = control1Y.coerceIn(chartTop, chartBottom)
                    val clampedControl2X = control2X.coerceIn(chartLeft, chartRight)
                    val clampedControl2Y = control2Y.coerceIn(chartTop, chartBottom)

                    path.cubicTo(
                        clampedControl1X, clampedControl1Y,
                        clampedControl2X, clampedControl2Y,
                        currentPoint.first, currentPoint.second
                    )
                }
            }

            // 绘制当前组的曲线段
            canvas.drawPath(path, curvePaint)
        }

        // 为孤立的单个点绘制带斜度的短线段
        val shortLineLength = dp2px(8f) // 短线段的长度
        for (isolatedPointWithIndex in isolatedPointsWithIndex) {
            val index = isolatedPointWithIndex.first
            val isolatedPoint = isolatedPointWithIndex.second
            val centerX = isolatedPoint.first
            val centerY = isolatedPoint.second

            // 寻找左右最近的有效数据点来计算斜率
            var leftPoint: Pair<Float, Float>? = null
            var rightPoint: Pair<Float, Float>? = null

            // 向左查找最近的有效点
            for (i in index - 1 downTo 0) {
                if (dataValues[i].mValue > 0.0f) {
                    val clampedValue = dataValues[i].mValue.coerceIn(yAxisMinValue, yAxisMaxValue)
                    val normalizedValue = if (yAxisValueRange > 0) (clampedValue - yAxisMinValue) / yAxisValueRange else 0f
                    val pointX = calculatePointX(i, yAxisBarX)
                    val pointY = chartPaddingTop + chartHeight * (1 - normalizedValue)
                    leftPoint = Pair(pointX, pointY)
                    break
                }
            }

            // 向右查找最近的有效点
            for (i in index + 1 until dataValues.size) {
                if (dataValues[i].mValue > 0.0f) {
                    val clampedValue = dataValues[i].mValue.coerceIn(yAxisMinValue, yAxisMaxValue)
                    val normalizedValue = if (yAxisValueRange > 0) (clampedValue - yAxisMinValue) / yAxisValueRange else 0f
                    val pointX = calculatePointX(i, yAxisBarX)
                    val pointY = chartPaddingTop + chartHeight * (1 - normalizedValue)
                    rightPoint = Pair(pointX, pointY)
                    break
                }
            }

            // 计算相邻数据点的平均间距
            val averageSpacing = if (dataValues.size > 1) {
                yAxisBarX / (dataValues.size - 1)
            } else {
                dp2px(20f) // 默认间距
            }

            // 短线段长度为相邻点间距的一半，但不超过设定的最大长度
            val actualLineLength = minOf(shortLineLength, averageSpacing / 2)
            val halfLength = actualLineLength / 2

            // 根据左右点计算斜率和线段端点
            val lineSegment = when {
                leftPoint != null && rightPoint != null -> {
                    // 两边都有点，计算通过三点的斜率
                    val slope = (rightPoint.second - leftPoint.second) / (rightPoint.first - leftPoint.first)
                    val deltaY = slope * halfLength

                    Pair(
                        Pair(
                            (centerX - halfLength).coerceIn(chartLeft, chartRight),
                            (centerY - deltaY).coerceIn(chartTop, chartBottom)
                        ),
                        Pair(
                            (centerX + halfLength).coerceIn(chartLeft, chartRight),
                            (centerY + deltaY).coerceIn(chartTop, chartBottom)
                        )
                    )
                }
                leftPoint != null -> {
                    // 只有左边有点，延续左边点到当前点的斜率
                    val slope = (centerY - leftPoint.second) / (centerX - leftPoint.first)
                    val deltaY = slope * halfLength

                    Pair(
                        Pair(
                            (centerX - halfLength).coerceIn(chartLeft, chartRight),
                            (centerY - deltaY).coerceIn(chartTop, chartBottom)
                        ),
                        Pair(
                            (centerX + halfLength).coerceIn(chartLeft, chartRight),
                            (centerY + deltaY).coerceIn(chartTop, chartBottom)
                        )
                    )
                }
                rightPoint != null -> {
                    // 只有右边有点，延续当前点到右边点的斜率
                    val slope = (rightPoint.second - centerY) / (rightPoint.first - centerX)
                    val deltaY = slope * halfLength

                    Pair(
                        Pair(
                            (centerX - halfLength).coerceIn(chartLeft, chartRight),
                            (centerY - deltaY).coerceIn(chartTop, chartBottom)
                        ),
                        Pair(
                            (centerX + halfLength).coerceIn(chartLeft, chartRight),
                            (centerY + deltaY).coerceIn(chartTop, chartBottom)
                        )
                    )
                }
                else -> {
                    // 左右都没有点，绘制水平线段
                    Pair(
                        Pair(
                            (centerX - halfLength).coerceIn(chartLeft, chartRight),
                            centerY
                        ),
                        Pair(
                            (centerX + halfLength).coerceIn(chartLeft, chartRight),
                            centerY
                        )
                    )
                }
            }

            // 解构方式
            val startPoint = lineSegment.first
            val endPoint = lineSegment.second
            val startX = startPoint.first
            val startY = startPoint.second
            val endX = endPoint.first
            val endY = endPoint.second

            // 绘制带斜度的短线段
            canvas.drawLine(startX, startY, endX, endY, curvePaint)
        }
    }

    /**
     * 绘制曲线上的指示点（替换原来的圆圈指示点）
     */
    private fun drawCurveIndicatorPoints(canvas: Canvas, chartHeight: Float) {
        if (dataValues.isEmpty()) return

        // 计算Y轴文字区域的位置
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 获取Y轴范围
        val yAxisMinValue = yAxisStages.first()
        val yAxisMaxValue = yAxisStages.last()
        val yAxisValueRange = yAxisMaxValue - yAxisMinValue

        // 找到最小值和最大值的数据点
        var minValueIndex = -1
        var maxValueIndex = -1
        var globalMinValue = Float.MAX_VALUE
        var globalMaxValue = Float.MIN_VALUE

        // 遍历所有有效数据，找到全局最小值和最大值
        for (i in dataValues.indices) {
            val data = dataValues[i]

            // 只考虑有效数据点
            if (data.mValue > 0.0f) {
                if (data.mValue < globalMinValue) {
                    globalMinValue = data.mValue
                    minValueIndex = i
                }

                if (data.mValue > globalMaxValue) {
                    globalMaxValue = data.mValue
                    maxValueIndex = i
                }
            }
        }

        // 圆圈半径
        val circleRadius = dp2px(4f)

        // 绘制最小值指示圆圈
        if (minValueIndex >= 0) {
            val data = dataValues[minValueIndex]
            val clampedValue = data.mValue.coerceIn(yAxisMinValue, yAxisMaxValue)
            val normalizedValue = if (yAxisValueRange > 0) (clampedValue - yAxisMinValue) / yAxisValueRange else 0f

            val circleX = calculatePointX(minValueIndex, yAxisBarX)
            val circleY = chartPaddingTop + chartHeight * (1 - normalizedValue)

            // 绘制圆圈（使用填充样式）
            curvePointPaint.style = Paint.Style.FILL
            curvePointPaint.color = activeBarColor
            canvas.drawCircle(circleX, circleY, circleRadius, curvePointPaint)

            // 绘制圆圈边框（使用描边样式）
            curvePointPaint.style = Paint.Style.STROKE
            curvePointPaint.color = Color.WHITE
            curvePointPaint.strokeWidth = dp2px(1f)
            canvas.drawCircle(circleX, circleY, circleRadius, curvePointPaint)

            // 在圆圈下方绘制数值
            val valueText = if (data.mValue % 1.0f == 0.0f) {
                data.mValue.toInt().toString()
            } else {
                String.format("%.1f", data.mValue)
            }

            val textWidth = valueTextPaint.measureText(valueText)
            val halfTextWidth = textWidth / 2
            val adjustedTextX = when {
                circleX - halfTextWidth < 0 -> halfTextWidth
                circleX + halfTextWidth > yAxisBarX -> yAxisBarX - halfTextWidth
                else -> circleX
            }

            val textY = circleY + circleRadius + dp2px(5f) + (valueTextPaint.textSize / 2)
            canvas.drawText(valueText, adjustedTextX, textY, valueTextPaint)
        }

        // 绘制最大值指示圆圈
        if (maxValueIndex >= 0 && maxValueIndex != minValueIndex) {
            val data = dataValues[maxValueIndex]
            val clampedValue = data.mValue.coerceIn(yAxisMinValue, yAxisMaxValue)
            val normalizedValue = if (yAxisValueRange > 0) (clampedValue - yAxisMinValue) / yAxisValueRange else 0f

            val circleX = calculatePointX(maxValueIndex, yAxisBarX)
            val circleY = chartPaddingTop + chartHeight * (1 - normalizedValue)

            // 绘制圆圈（使用填充样式）
            curvePointPaint.style = Paint.Style.FILL
            curvePointPaint.color = activeBarColor
            canvas.drawCircle(circleX, circleY, circleRadius, curvePointPaint)

            // 绘制圆圈边框（使用描边样式）
            curvePointPaint.style = Paint.Style.STROKE
            curvePointPaint.color = Color.WHITE
            curvePointPaint.strokeWidth = dp2px(1f)
            canvas.drawCircle(circleX, circleY, circleRadius, curvePointPaint)

            // 在圆圈上方绘制数值
            val valueText = if (data.mValue % 1.0f == 0.0f) {
                data.mValue.toInt().toString()
            } else {
                String.format("%.1f", data.mValue)
            }

            val textWidth = valueTextPaint.measureText(valueText)
            val halfTextWidth = textWidth / 2
            val adjustedTextX = when {
                circleX - halfTextWidth < 0 -> halfTextWidth
                circleX + halfTextWidth > yAxisBarX -> yAxisBarX - halfTextWidth
                else -> circleX
            }

            val textY = circleY - circleRadius - dp2px(5f)
            canvas.drawText(valueText, adjustedTextX, textY, valueTextPaint)
        }
    }

    /**
     * 绘制背景柱
     */
    private fun drawBackgroundBars(canvas: Canvas, chartHeight: Float, yAxisBarX: Float, yAxisMinValue: Float, yAxisMaxValue: Float, yAxisValueRange: Float) {
        var backgroundStart = -1
        var backgroundEnd = -1

        for (i in dataValues.indices) {
            val isSelected = dataValues[i].selectBg

            if (isSelected) {
                if (backgroundStart == -1) {
                    backgroundStart = i
                }
                backgroundEnd = i
            } else {
                if (backgroundStart != -1) {
                    // 绘制连续的背景柱
                    drawContinuousBackground(canvas, chartHeight, yAxisBarX, backgroundStart, backgroundEnd)
                    backgroundStart = -1
                    backgroundEnd = -1
                }
            }
        }

        // 处理最后一段背景柱
        if (backgroundStart != -1) {
            drawContinuousBackground(canvas, chartHeight, yAxisBarX, backgroundStart, backgroundEnd)
        }
    }

    /**
     * 绘制连续的背景柱
     */
    private fun drawContinuousBackground(canvas: Canvas, chartHeight: Float, yAxisBarX: Float, startIndex: Int, endIndex: Int) {
        val left = if (dataValues.size <= 1) {
            0f
        } else {
            calculatePointX(startIndex, yAxisBarX) - (yAxisBarX / (dataValues.size - 1)) / 2
        }

        val right = if (dataValues.size <= 1) {
            yAxisBarX
        } else {
            calculatePointX(endIndex, yAxisBarX) + (yAxisBarX / (dataValues.size - 1)) / 2
        }

        val top = chartPaddingTop
        val bottom = chartPaddingTop + chartHeight

        rectF.set(left, top, right, bottom)
        canvas.drawRect(rectF, backgroundBarPaint)
    }

    /**
     * 绘制触摸实线
     */
    private fun drawTouchLine(canvas: Canvas, chartHeight: Float) {
        // 绘制垂直触摸线
        canvas.drawLine(
            touchLineX,
            chartPaddingTop,
            touchLineX,
            chartPaddingTop + chartHeight,
            touchLinePaint
        )
    }

    /**
     * 绘制X轴时间标签
     */
    private fun drawTimeLabels(canvas: Canvas, chartHeight: Float) {
        // 计算Y轴文字区域的位置（去除色块宽度）
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        val labelY = chartPaddingTop + chartHeight + dp2px(20f)

        // 绘制时间标签
        for (i in timeLabels.indices) {
            val labelX = when (i) {
                0 -> 0f // 第一个标签（00:00）与图表左边对齐
                timeLabels.size - 1 -> yAxisBarX // 最后一个标签位于图表右边界
                else -> {
                    // 动态计算中间时间点的X位置
                    val segmentSize = yAxisBarX / (timeLabels.size - 1)
                    i * segmentSize
                }
            }

            // 第一个标签使用左对齐，其他标签使用居中对齐
            if (i == 0) {
                val originalAlign = textPaint.textAlign
                textPaint.textAlign = Paint.Align.LEFT
                canvas.drawText(timeLabels[i], labelX, labelY, textPaint)
                textPaint.textAlign = originalAlign
            } else {
                canvas.drawText(timeLabels[i], labelX, labelY, textPaint)
            }
        }
    }

    /**
     * 绘制右侧Y轴标记文字（去除色块）
     */
    private fun drawYAxisStageIndicators(canvas: Canvas, chartHeight: Float) {
        // 动态计算最大文字宽度
        val maxTextWidth = calculateMaxYAxisTextWidth()

        // 计算总的指示器宽度（去除色块宽度）
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth

        // Y轴文字的X位置：从控件最右边往左计算
        val yAxisTextX = width - totalIndicatorWidth

        // 获取Y轴范围
        val minValue = yAxisStages.first()
        val maxValue = yAxisStages.last()
        val valueRange = maxValue - minValue

        // 绘制所有阶段的标记文字（包括第一个起始值）
        for (i in yAxisStages.indices) {
            val stage = yAxisStages[i]

            // 计算网格线的Y位置
            val normalizedStage = (stage - minValue) / valueRange
            val gridLineY = when (i) {
                0 -> {
                    // 底部网格线位置（在图表底部下方1dp处）
                    chartPaddingTop + chartHeight + dp2px(1f)
                }
                yAxisStages.size - 1 -> {
                    // 顶部网格线位置（在图表顶部上方1dp处）
                    chartPaddingTop + chartHeight * (1 - normalizedStage) - dp2px(1f)
                }
                else -> {
                    // 中间网格线位置
                    chartPaddingTop + chartHeight * (1 - normalizedStage)
                }
            }

            // 计算文字的Y位置
            val textMetrics = yAxisTextPaint.fontMetrics
            val textHeight = textMetrics.descent - textMetrics.ascent

            val textY = when (i) {
                0 -> {
                    // 底部标记文字：显示在底部粗实线的上方
                    gridLineY - textMetrics.descent - dp2px(2f)
                }
                yAxisStages.size - 1 -> {
                    // 顶部标记文字：显示在顶部粗实线的下方
                    gridLineY - textMetrics.ascent + dp2px(2f)
                }
                else -> {
                    // 中间标记文字：与网格线垂直居中对齐
                    gridLineY - textMetrics.ascent - textHeight / 2
                }
            }

            val textX = yAxisTextX + yAxisTextMargin

            // 使用阶段值的toString()作为标签，去掉小数点后的0
            val label = if (stage % 1.0f == 0.0f) {
                stage.toInt().toString()
            } else {
                stage.toString()
            }
            canvas.drawText(if(yAxisTextEx.isNullOrEmpty()) label else "$label$yAxisTextEx", textX, textY, yAxisTextPaint)
        }
    }

    /**
     * 绘制基准线
     * 根据mBasic值在Y轴对应位置绘制虚线
     */
    private fun drawBasicLine(canvas: Canvas, chartHeight: Float) {
        if (mBasic <= 0f) return // 如果基准值无效，不绘制

        // 计算Y轴文字区域的位置
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 获取Y轴范围
        val yAxisMinValue = yAxisStages.first()
        val yAxisMaxValue = yAxisStages.last()
        val yAxisValueRange = yAxisMaxValue - yAxisMinValue

        // 检查基准值是否在Y轴范围内
        if (mBasic < yAxisMinValue || mBasic > yAxisMaxValue) return

        // 计算基准线的Y位置
        val normalizedBasic = (mBasic - yAxisMinValue) / yAxisValueRange
        val basicLineY = chartPaddingTop + chartHeight * (1 - normalizedBasic)

        // 绘制基准线（从图表左边界到Y轴文字区域右边界）
        val lineStartX = 0f
        val lineEndX = yAxisBarX

        canvas.drawLine(
            lineStartX,
            basicLineY,
            lineEndX,
            basicLineY,
            basicLinePaint
        )
    }

    /**
     * 绘制Y轴区间背景
     */
    private fun drawYRangeBackground(canvas: Canvas, chartHeight: Float) {
        // 计算Y轴文字区域的位置
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 获取Y轴范围
        val yAxisMinValue = yAxisStages.first()
        val yAxisMaxValue = yAxisStages.last()
        val yAxisValueRange = yAxisMaxValue - yAxisMinValue

        // 检查区间值是否在Y轴范围内
        if (yRangeStartValue < yAxisMinValue || yRangeEndValue > yAxisMaxValue ||
            yRangeStartValue >= yRangeEndValue) {
            return // 区间无效，不绘制
        }

        // 限制区间值在Y轴范围内
        val clampedStartValue = yRangeStartValue.coerceIn(yAxisMinValue, yAxisMaxValue)
        val clampedEndValue = yRangeEndValue.coerceIn(yAxisMinValue, yAxisMaxValue)

        // 计算区间在图表中的Y位置
        val normalizedStartValue = (clampedStartValue - yAxisMinValue) / yAxisValueRange
        val normalizedEndValue = (clampedEndValue - yAxisMinValue) / yAxisValueRange

        // 计算背景矩形的位置（注意Y轴是倒置的）
        val backgroundTop = chartPaddingTop + chartHeight * (1 - normalizedEndValue)
        val backgroundBottom = chartPaddingTop + chartHeight * (1 - normalizedStartValue)
        val backgroundLeft = 0f
        val backgroundRight = yAxisBarX

        // 绘制区间背景矩形
        rectF.set(backgroundLeft, backgroundTop, backgroundRight, backgroundBottom)
        canvas.drawRect(rectF, yRangeBackgroundPaint)
    }

    /**
     * 计算Y轴标记文字的最大宽度
     */
    private fun calculateMaxYAxisTextWidth(): Float {
        var maxTextWidth = 0f
        // 计算所有阶段值作为标签的宽度（包括第一个起始值）
        for (i in yAxisStages.indices) {
            val label = if (yAxisStages[i] % 1.0f == 0.0f) {
                yAxisStages[i].toInt().toString()
            } else {
                yAxisStages[i].toString()
            }
            val textWidth = yAxisTextPaint.measureText(label)
            if (textWidth > maxTextWidth) {
                maxTextWidth = textWidth + dp2px(14f)
            }
        }
        return maxTextWidth
    }

    private fun findViewPager2(): androidx.viewpager2.widget.ViewPager2? {
        var parent = parent
        while (parent != null) {
            if (parent is androidx.viewpager2.widget.ViewPager2) {
                return parent
            }
            parent = parent.parent
        }
        return null
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {

        if (dataValues.isNullOrEmpty()) return true//无数据是直接透传触摸
        val viewPager2 = findViewPager2()

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {

                if (isTouchInChartArea(event.x, event.y)) {
                    // 直接禁用ViewPager2的用户输入
                    viewPager2?.isUserInputEnabled = false
                    parent?.requestDisallowInterceptTouchEvent(true)
                    handleTouch(event.x)
                    return true
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if (isTouching && isTouchInChartArea(event.x, event.y)) {
                    handleTouch(event.x)
                    return true
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                if (isTouching) {
                    // 恢复ViewPager2的用户输入
                    viewPager2?.isUserInputEnabled = true
                    parent?.requestDisallowInterceptTouchEvent(false)
                    handleTouchRelease()
                    return true
                }
            }
        }
        return super.onTouchEvent(event)
    }

    /**
     * 检查触摸点是否在图表区域内
     */
    private fun isTouchInChartArea(x: Float, y: Float): Boolean {
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        return x >= 0 && x <= yAxisBarX &&
                y >= chartPaddingTop && y <= height - chartPaddingBottom
    }

    /**
     * 处理触摸事件
     */
    private fun handleTouch(touchX: Float) {
        val maxTextWidth = calculateMaxYAxisTextWidth()
        val totalIndicatorWidth = yAxisTextMargin + maxTextWidth
        val yAxisBarX = width - totalIndicatorWidth

        // 找到最接近的数据点
        var closestIndex = -1
        var minDistance = Float.MAX_VALUE

        for (i in dataValues.indices) {
            val pointX = calculatePointX(i, yAxisBarX)
            val distance = kotlin.math.abs(touchX - pointX)
            if (distance < minDistance) {
                minDistance = distance
                closestIndex = i
            }
        }

        if (closestIndex >= 0 && closestIndex < dataValues.size) {
            touchedBarIndex = closestIndex
            touchLineX = calculatePointX(closestIndex, yAxisBarX)
            isTouching = true

            // 通知监听器
            val data = dataValues[closestIndex]
            val timeLabel = getTimeLabel(closestIndex)
            touchListener?.onBarTouched(closestIndex, data.minValue, data.mValue, timeLabel)

            invalidate()
        }
    }

    /**
     * 处理触摸释放事件
     */
    private fun handleTouchRelease() {
        isTouching = false
        touchedBarIndex = -1
        touchListener?.onTouchReleased()
        invalidate()
    }

    /**
     * 根据索引获取时间标签
     */
    private fun getTimeLabel(index: Int): String {
        // 改为动态计算，基于实际数据点数量
        val totalHours = 24.0
        val hour = (index * totalHours / dataValues.size).toInt()
        val minuteProgress = (index * totalHours / dataValues.size) - hour
        val minute = (minuteProgress * 60).toInt()
        return String.format("%02d:%02d", hour, minute)
    }

    // 公共方法

    /**
     * 设置Y轴阶段配置
     */
    fun setYAxisStages(stages: FloatArray) {
        yAxisStages = stages
        invalidate()
    }

    /**
     * 设置数据
     */
    fun setData(data: List<CusChartData>) {
        dataValues.clear()
        dataValues.addAll(data)
        invalidate()
    }


    /**
     * 获取数据
     */
    fun getData():List<CusChartData> {
       return dataValues
    }

    /**
     * 设置颜色
     */
    fun setColors(activeColor: Int, inactiveColor: Int) {
        activeBarColor = activeColor
        inactiveBarColor = inactiveColor
        curvePaint.color = activeColor
        curvePointPaint.color = activeColor
        invalidate()
    }

    /**
     * 设置触摸监听器
     */
    fun setOnBarTouchListener(listener: OnBarTouchListener?) {
        touchListener = listener
    }

    /**
     * 设置柱子顶部圆角
     * @param enable true: 启用顶部圆角, false: 禁用顶部圆角
     */
    fun setBarTopRounding(enable: Boolean) {
        enableBarTopRounding = enable
        invalidate()
    }

    /**
     * 设置柱子底部圆角
     * @param enable true: 启用底部圆角, false: 禁用底部圆角
     */
    fun setBarBottomRounding(enable: Boolean) {
        enableBarBottomRounding = enable
        invalidate()
    }

    /**
     * 设置柱子圆角（同时控制顶部和底部）
     * @param enableTop 是否启用顶部圆角
     * @param enableBottom 是否启用底部圆角
     */
    fun setBarRounding(enableTop: Boolean, enableBottom: Boolean) {
        enableBarTopRounding = enableTop
        enableBarBottomRounding = enableBottom
        invalidate()
    }

    /**
     * 设置X轴中间线绘制方式
     * @param enable true: 绘制8px高度的实线, false: 绘制点虚线
     */
    fun setXAxisSolidLineEnabled(enable: Boolean) {
        enableXAxisSolidLine = enable
        invalidate()
    }

    /**
     * 获取X轴中间线绘制方式
     * @return true: 实线模式, false: 虚线模式
     */
    fun isXAxisSolidLineEnabled(): Boolean {
        return enableXAxisSolidLine
    }

    /**
     * 设置基准值
     * @param basic 基准值
     */
    fun setBasicValue(basic: Float) {
        mBasic = basic
        invalidate()
    }

    /**
     * 获取基准值
     * @return 当前基准值
     */
    fun getBasicValue(): Float {
        return mBasic
    }

    /**
     * 设置曲线颜色
     */
    fun setCurveColor(color: Int) {
        curvePaint.color = color
        curvePointPaint.color = color
        activeBarColor = color
        invalidate()
    }

    /**
     * 设置曲线宽度
     */
    fun setCurveWidth(width: Float) {
        curvePaint.strokeWidth = width
        invalidate()
    }

    fun setTimeLabels(mData : List<String>){
        timeLabels = mData.toTypedArray()
        invalidate()
    }

    /**
     * 新增：设置Y轴区间背景
     * @param startValue 区间开始值
     * @param endValue 区间结束值
     * @param backgroundColor 背景颜色
     */
    fun setYRangeBackground(startValue: Float, endValue: Float, backgroundColor: Int = yRangeBackgroundColor) {
        yRangeStartValue = startValue
        yRangeEndValue = endValue
        yRangeBackgroundColor = backgroundColor
        yRangeBackgroundPaint.color = backgroundColor
        yRangeBackgroundEnabled = true
        invalidate()
    }

    /**
     * 新增：设置Y轴区间背景透明度
     * @param alpha 透明度 (0-255)
     */
    fun setYRangeBackgroundAlpha(alpha: Int) {
        yRangeBackgroundPaint.alpha = alpha.coerceIn(0, 255)
        invalidate()
    }

    /**
     * 新增：启用或禁用Y轴区间背景
     * @param enabled 是否启用
     */
    fun setYRangeBackgroundEnabled(enabled: Boolean) {
        yRangeBackgroundEnabled = enabled
        invalidate()
    }

    /**
     * 新增：清除Y轴区间背景
     */
    fun clearYRangeBackground() {
        yRangeBackgroundEnabled = false
        invalidate()
    }

    /**
     * 新增：获取Y轴区间背景是否启用
     */
    fun isYRangeBackgroundEnabled(): Boolean {
        return yRangeBackgroundEnabled
    }

    /**
     * 新增：获取Y轴区间开始值
     */
    fun getYRangeStartValue(): Float {
        return yRangeStartValue
    }

    /**
     * 新增：获取Y轴区间结束值
     */
    fun getYRangeEndValue(): Float {
        return yRangeEndValue
    }
}